__author__ = 'Muscle'

from mui.muicomponent import MUIComponent
import mui.color as color
from mui.Widgets.muitext import MUIText, TextBase
import mui.muianim as anim


class TipBase:
    """ TipBase is an abstrat class, you can derived from it to support showing tips
    """
    def __init__(self, **kwargs):
        assert isinstance(self, MUIComponent)
        self.tips = kwargs.get('tips', '')
        self.tipdelay = 0.5
        self.__preMousePos = 0, 0
        self.bind('Enable Change', self.hideTips)
        self.bind('Mouse Move', self.__onMouseMove)
        self.bind('Mouse Leave', self.hideTips)
        self.bind('Mouse Down', self.hideTips)
        self.bind('Mouse RDown', self.hideTips)
        self.bind('Visible Change', self.hideTips, noarg = True)
        self.changeEvent('tips', self.__onTipsChange)

    def __onTipsChange(self):
        if self.isMouseOver:
            self.hideTips()
            self.__postShowTips()

    def __onMouseMove(self, comp, x, y, dx, dy):
        self.__preMousePos = x, y
        self.__postShowTips()

    def __postShowTips(self):
        if self.tips and not self.dead and self.window:
            anim.unschedule(self.showTips)
            if self.tipdelay > 0:
                anim.schedule_once(self.showTips, self.tipdelay)
            else:
                anim.schedule_once(self.showTips, 0)
        else:
            self.hideTips()

    def showTips(self):
        """ show tips on the windows
        """
        x, y = self.__preMousePos
        if self.tips and not self.dead and self.window:
            tips = self.tips

            if hasattr(self, 'command') and self.command:
                command = '<'+self.command+'>'

                # got accelerator
                parent = self.parent
                objs = []
                keymaps = {}
                while parent:
                    if hasattr(parent, 'keymaps') and parent.keymaps:
                        objs.append(parent)
                        #keymaps.update(parent.keymaps)
                    parent = parent.parent

                if objs:
                    for obj in objs[::-1]:
                        keymaps.update(obj.keymaps)

                subTips = ''
                for key, cmd in keymaps.items():
                    if command in cmd:
                        if key == ' ':
                            key = 'SPACE'
                        if subTips:
                            subTips += ', %s' % key
                        else:
                            subTips += '%s' % key

                if subTips:
                    tips = tips + '  (%s)' % (subTips)

            self.window.showToolTips(tips, self.local2global(x, y))

    def hideTips(self, *_argv):
        """ hide tips
        """
        if not self.dead and self.window:
            anim.unschedule(self.showTips)
            self.window.hideToolTips()

TipBaseEx = TipBase

class MUITipText(MUIText, TipBase):
    """ TipText mean text support tips
    """
    def __init__(self, parent=None, **argd):
        MUIText.__init__(self, parent, **argd)
        TipBase.__init__(self, **argd)

        self.autotips = True

        self.bind('Size Change', self.onAutotips)
        self.changeEvent('text', self.onAutotips)
        self.onAutotips()
        
    def onAutotips(self):
        self.blind = not self.autotips
        if self.autotips: # and self.tips != self.text:
            tw, th = self.calTextSize(self.text)
            if self.width < tw or (self.height < th ):
                self.tips = self.text
            else:
                self.tips = ''

    def getContent(self):
        if self.autotips and self.tips:
            content = super(MUITipText, self).getContent()

            constraint = self.width
            truncated = ''
            remain = content

            # ...
            w = self.calTextSize('...')[0]
            if w > constraint:
                return '...'
            # truncated...
            while remain:
                h = (len(remain) + 1) / 2
                concat, remain = remain[:h], remain[h:]
                display = truncated + concat + '...'
                w = self.calTextSize(display, maxWidth = 10000)[0]
                if w == constraint:     # luckily equal to constraint
                    return display
                elif w < constraint:    # less than constraint
                    truncated += concat
                elif len(concat) > 1:   # over constraint
                    remain = concat
                else:                   # over constraint even only one more character
                    remain = None
            return truncated + '...'

        return super(MUITipText, self).getContent()

class MUITooltips(MUIText):
    """ tool tip object for internal use (used in window)
    """
    def __init__(self, parent = None):
        MUIText.__init__(self, parent)
        self.autosize = True
        self.bgColor = color.paper
        self.fontColor = color.black
        self.border = 30, 15
        self.visible = False

    def onAutoSize(self):
        if self.autosize:
            maxW = max(10, self.window.width - self.globalPosition[0]- 30)
            tw, th = self.calTextSize(self.text, maxWidth = maxW, maxHeight = 10000)
            self.size = tw + self.border[0], th + self.border[1]


    def on_draw(self, renderer):
        # draw background
        MUIComponent.on_draw(self, renderer)

        # draw border
        if not self.background:
            self.drawBorder(renderer, 1, color.black)

        # draw text
        TextBase.draw(self, renderer)

    def parent2local(self, x, y):
        """
        @param x, y: (x, y) in parent coordinate
        @return: (x, y) in local coordinate
        """

        return x  - self.left, y - self.top

    def local2parent(self, x, y):
        """
        @param x, y: (x, y) in local coordinate
        @return: (x, y) in parent coordinate
        """
        return (x + self.left) , (y + self.top)
